package top.suven.base.http.admin.frame.shiro;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import top.suven.base.core.db.DataSourceEnum;
import top.suven.base.core.db.DataSourceGroup;
import top.suven.base.core.db.DataSourceGroupNameEnum;
import top.suven.base.core.db.DataSourceHolder;
import top.suven.base.http.admin.old.model.SysAdmin;
import top.suven.base.http.admin.old.service.SysAdminService;
import top.suven.base.http.admin.sec.model.AdminRole;
import top.suven.base.http.admin.sec.model.Role;
import top.suven.base.http.admin.sec.model.RoleMenu;
import top.suven.base.http.admin.sec.service.RoleMenuService;
import top.suven.base.http.admin.sec.service.RoleService;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class AuthRealm extends AuthorizingRealm {
//    private String clientId;
//    private String clientSecret;
//    private String accessTokenUrl;
//    private String userInfoUrl;
//    private String redirectUrl;
//
//    public void setClientId(String clientId) {
//        this.clientId = clientId;
//    }
//
//    public void setClientSecret(String clientSecret) {
//        this.clientSecret = clientSecret;
//    }
//
//    public void setAccessTokenUrl(String accessTokenUrl) {
//        this.accessTokenUrl = accessTokenUrl;
//    }
//
//    public void setUserInfoUrl(String userInfoUrl) {
//        this.userInfoUrl = userInfoUrl;
//    }
//
//    public void setRedirectUrl(String redirectUrl) {
//        this.redirectUrl = redirectUrl;
//    }
//
//    @Override
//    public boolean supports(AuthenticationToken token) {
//        return token instanceof OAuth2Token;//表示此Realm只支持OAuth2Token类型
//    }
//
//    @Override
//    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//        return authorizationInfo;
//    }
//
//    @Override
//    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        OAuth2Token oAuth2Token = (OAuth2Token) token;
//        String code = oAuth2Token.getAuthCode();
//        //下面这段代码是解决评论里说的那个bug的一种方式。
//        Subject currentUser = SecurityUtils.getSubject();
//        Session session = currentUser.getSession();
//        if(code!=null){//第一次code不是null，放到session里
//            session.setAttribute("code", code);
//        }else{//第二次 code是null，从session里拿。
//            code=(String) session.getAttribute("code");
//        }
//        //上面是评论里某人修复bug的一种方式
//        String username = extractUsername(code);
//
//        SimpleAuthenticationInfo authenticationInfo =
//                new SimpleAuthenticationInfo(username, code, getName());
//        return authenticationInfo;
//    }
//
//    private String extractUsername(String code) {
//
//        try {
//            OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
//
//            OAuthClientRequest accessTokenRequest = OAuthClientRequest
//                    .tokenLocation(accessTokenUrl)
//                    .setGrantType(GrantType.AUTHORIZATION_CODE)
//                    .setClientId(clientId)
//                    .setClientSecret(clientSecret)
//                    .setCode(code)
//                    .setRedirectURI(redirectUrl)
//                    .buildQueryMessage();
//
//            OAuthAccessTokenResponse oAuthResponse = oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);
//
//            String accessToken = oAuthResponse.getAccessToken();
//            Long expiresIn = oAuthResponse.getExpiresIn();
//
//            OAuthClientRequest userInfoRequest = new OAuthBearerClientRequest(userInfoUrl)
//                    .setAccessToken(accessToken).buildQueryMessage();
//
//            OAuthResourceResponse resourceResponse = oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
//            String username = resourceResponse.getBody();
//            return username;
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new AuthenticationException (e);
//        }
//    }
    @Autowired
    private SysAdminService sysAdminService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private RoleMenuService roleMenuService;

    //认证.登录
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token
        String username = utoken.getUsername();
        DataSourceGroup dataSource = DataSourceHolder.getDataSource();
        if(dataSource == null){
            DataSourceGroup dataChooseParam = new DataSourceGroup(DataSourceGroupNameEnum.DATA_NAME_USER.name(), DataSourceEnum.MASTER);
            DataSourceHolder.putDataSource(dataChooseParam);
        }
        //获取管理员信息
        SysAdmin admin = sysAdminService.getSysAdmin(username);
        if(admin == null){
            return null;
        }
        //获取管理员角色列表
        AdminRole adminRole = new AdminRole();
        adminRole.setAdminCode(admin.getAdminCode());
        List<Role> roleList =  roleService.getRoleValidListByAdminCode(adminRole);
        do{
            if(roleList == null || roleList.isEmpty()){
                break;
            }
            //根据管理员角色列表获取权限列表
            List<String> roleCodeList = roleList.stream().map(e->e.getRoleCode()).collect(Collectors.toList());
            List<RoleMenu> roleMenuList = roleMenuService.getRoleMenuByRoleCodeList(roleCodeList);
            if(roleMenuList == null || roleMenuList.isEmpty()){
                admin.setRoleList(roleList);
                break;
            }
            //将权限列表设置到对应的权限中
            Map<String,List<RoleMenu>> roleMenuMap = roleMenuList.stream().collect(Collectors.groupingBy(RoleMenu::getRoleCode));
            for(Role role:roleList){
                role.setRoleMenuList(roleMenuMap.get(role.getRoleCode()));
            }
            admin.setRoleList(roleList);
        }while (false);
        return new SimpleAuthenticationInfo(admin, admin.getAdminPwd(),getName());//放入shiro.调用CredentialsMatcher检验密码
    }
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        SysAdmin admin = (SysAdmin) principal.fromRealm(getName()).iterator().next();//获取session中的用户
        Set<String> permissions = new HashSet<>();

        do{
            if(admin == null){
                break;
            }
            List<Role> roleList = admin.getRoleList();
            if(roleList == null || roleList.isEmpty()){
                break;
            }
            for(Role role:roleList){
                permissions.addAll(role.getRoleMenuList().stream().filter(e-> StringUtils.isNotBlank(e.getMenuCode())).map(e->e.getMenuCode()).collect(Collectors.toSet()));
            }
        }while (false);
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);//将权限放入shiro中.
        return info;
    }

}